package main.java;

import java.io.File;
import net.jtank.input.KeyCode;
import net.jtank.input.KeyReleasedEvent;
import net.jtank.input.MousePressedEvent;

import org.jagatoo.logging.Log;
import org.xith3d.base.Xith3DEnvironment;
import org.xith3d.loop.CanvasFPSListener;
import org.xith3d.loop.InputAdapterRenderLoop;
import org.xith3d.loop.opscheduler.Animatable;
import org.xith3d.loop.opscheduler.PickScheduler;
import org.xith3d.picking.NearestPickListener;
import org.xith3d.picking.PickResult;
import org.xith3d.render.Canvas3D;
import org.xith3d.resources.ResourceLocator;
import org.xith3d.scenegraph.BranchGroup;
import org.xith3d.schedops.movement.RotatableGroup;
import org.xith3d.ui.hud.HUD;
import org.xith3d.ui.hud.theming.WidgetTheme;
import org.xith3d.ui.hud.widgets.assemblies.ConsoleListener;
import org.xith3d.ui.hud.widgets.assemblies.HUDConsole;
import org.xith3d.utility.commands.Command;
import org.xith3d.utility.commands.CommandException;
import org.xith3d.utility.commands.CommandLine;
import org.xith3d.utility.commands.CommandProcessor;
import org.xith3d.utility.commands.impl.ExitCommand;

import main.java.commands.CmdShowScene;
import main.java.commands.CmdTest;
import main.java.scenes.SceneInterface;

/**
 * Default MainLoop of all Scenes...
 * Attention: Engine function calls are order dependend and can end up in strange bugs(on some plattforms) in wrong order...
 * @author Sven Berger
 *
 */
public class MainLoop extends InputAdapterRenderLoop implements ConsoleListener, NearestPickListener 
{
	private boolean showFPS=false;
	private ResourceManager ress=null;
	private CanvasFPSListener fps=null;
	private HUDConsole console;
	private CommandProcessor commandProcessor =null;
	private final CommandLine tmpCommandLine = new CommandLine();
	private SceneInterface actScene=null;
	private Canvas3D canvas3D;
	private Xith3DEnvironment xEnv;
	private PickScheduler pickScheder;
	private BranchGroup br;
		
	//setup next frame
	 public void prepareNextFrame( long gameTime, long frameTime, TimingMode tm )
	    {
	        super.prepareNextFrame( gameTime, frameTime, tm );
	        this.actScene.prepareNextFrame(gameTime, frameTime, tm);
	    }


	//todo make keys dynamic configurable...
	@Override
	 public void onKeyReleased( KeyReleasedEvent e )
	    {
	        switch ( e.getKeyCode() )
	        {
	            case KeyCode.VK_ESCAPE:
	            	this.ende();
	                break;
	            case KeyCode.VK_F1://show FPS after pressing F1
	            	if(this.showFPS)this.removeFPSListener(this.fps);
	            	else this.addFPSListener(this.fps);
	            	this.showFPS=!this.showFPS;
	            	break;
	            case KeyCode.VK_CIRCUMFLEX:
	            	this.console.popUp( !this.console.isPoppedUp() );
	            	break;
	            	
	        }
	    }
	
	/**
	 * @param env
	 * @param canvas
	 * @param resourceManager 
	 * @throws Exception 
	 */
	public MainLoop(Xith3DEnvironment env, Canvas3D canvas, ResourceManager resourceManager, SceneInterface scene) throws Exception
	{
		super();
		this.ress=resourceManager;
		this.canvas3D=canvas;
		this.xEnv=env;
		this.pickScheder = env.getPickScheduler();
		//register initial Scene
		this.registerScene(scene);
		
		final ResourceLocator resLoc = ResourceLocator.create( "resources/" );
		resLoc.createAndAddTSL( "textures" );
		//resLoc.createAndAddTSL( "hud-themes/resources/xith3d/hud/themes/" );
		
		//standard theme location
		HUD.setTheme( new WidgetTheme( new File( "resources/GTK.xwt" ) ) );
		
		HUD hud = new HUD(canvas,800f, this.getOperationScheduler() );
		this.console = new HUDConsole( hud.getResX(), 200f, this.ress.getLogchannel().getID(), false );
		this.console.addConsoleListener( this );
		hud.addWidget( this.console );
		//all debugmsg to console
		Log.getLogManager().registerLog( this.console );


		env.addHUD( hud, this.getInputManager() );

		this.addRenderEngine(env);
		this.getInputManager().registerKeyboardAndMouse( canvas );
		this.fps= new CanvasFPSListener(canvas);
		this.commandProcessor= new CommandProcessor( this.ress.getLogchannel() );
		this.commandProcessor.registerCommand( new ExitCommand( this ) );
		this.commandProcessor.registerCommand( new CmdTest(this.console));
		this.commandProcessor.registerCommand( new CmdShowScene(this));
		this.console.registerCommands( this.commandProcessor.getRegisteredCommands() );



		
	}
	@Override
	public void onCommandEntered(final HUDConsole console2, String commandLine)
	{
		this.tmpCommandLine.parse( commandLine );
		Command command = this.commandProcessor.getRegisteredCommand( this.tmpCommandLine.getKey() );
		if ( command != null )
		{
			try
			{
				this.ress.addMessag(command.execute( null, this.tmpCommandLine ));
			}
			catch(CommandException e)
			{
				e.printStackTrace();
				this.ress.addError(e.getStackTrace().toString());
			}
			}
		}

	/** Close the Client
	 * 
	 */
	public void ende()
	{
		this.ress.addMessag("Client closed");
        this.end(); //close program
	}
	/** Register a Scene that should be shown to the screen
	 * @param scene
	 */
	public void registerScene(final SceneInterface scene)
	{
		if(this.actScene!=null)this.actScene.unregisterScene();
		this.actScene=scene;
		this.br=this.actScene.registerScene(this.xEnv, this.canvas3D, this.ress,this);
		this.actScene.onRegister();
	}


	@Override
	public void onObjectPicked(PickResult nearest, Object userObject,
			long pickTime) {
		this.ress.addMessag( "You picked a shape called " +
                "\"" + nearest.getNode().getName() + "\"." );
		
	}


	@Override
	public void onPickingMissed(Object userObject, long pickTime) {
		 this.console.println( "You just picked nothing!" );
		
	}
	
	@Override
	 public void onMouseButtonPressed( MousePressedEvent e )
	 {
		if(this.br!=null)this.pickScheder.pickNearest(this.br, e.getButton(), e.getX(), e.getY(),(NearestPickListener) this );
	 }
	
		
}

